
-----------------------------------------------------------------------------------------
--
-- main.lua
--
-----------------------------------------------------------------------------------------
module(...,package.seeall)
local storyboard = require( "storyboard" )
local scene = storyboard.newScene()
display.setStatusBar( display.HiddenStatusBar )
-- forward declarations





local client, server, isClient, isServer, myPlayerID
local serverReceived, clientReceived, dragBodyServer, dragBodyClient, ballCollision, 
								sendFullFrame,sendFullFrameTimer, playerDropped, connectionAttemptFailed
local screenW, screenH, halfW, halfH = display.contentWidth, display.contentHeight, display.contentWidth*0.5, display.contentHeight*0.5
local physicsGroup, UIGroup, menuGroup,serverGroup = display.newGroup(), display.newGroup(), display.newGroup(),display.newGroup()
local clients = {} --contains the client objects that represent connections to clients
local physics = require "physics"
local widget = require "widget"
physics.start();
physics.setGravity(0,0);  --physics.setTimeStep( 1/60 );

local hostBtn,joinBtn,textWaiting,removeServer
local xPosBtn = display.contentWidth/ 4;
local yPosBtn = display.contentHeight - 40;
local widthButton = 140;
local heightButton = 25;
local singlePlayer=require("singlePlayer")

local function makeClient()
	print("Tao server")
	if(isServer) then --if we were a server before, we need to unregister all the event listeners
		--paddleDown:setFillColor(255,100,100)
		Runtime:removeEventListener("autolanPlayerDropped", playerDropped)
		Runtime:removeEventListener("autolanPlayerJoined", addPlayer)
		--paddleDown:removeEventListener("touch", dragBodyServer) --assign bottom padle to server
		Runtime:removeEventListener("autolanReceived", serverReceived) --all incoming packets sent to serverReceived
		Runtime:removeEventListener ( "enterFrame", onFrame1)
		timer.cancel(sendFullFrameTimer)
		isServer = false
	end
	print("making client")
	client = require("Client")
	client:start()
	client:scanServersInternet()
	isClient = true
	Runtime:addEventListener("autolanReceived", clientReceived) --all incoming packets are sent to clientReceived
	Runtime:addEventListener("autolanConnectionFailed", connectionAttemptFailed)
	Runtime:addEventListener("autolanDisconnected", connectionAttemptFailed)	
	--singlePlayer.mainPlay()
end

local function makeServer()
	if(isClient) then --if we were a client before, we need to unregister all the event listeners
		isClient = false
		--paddleUp:setFillColor(255,100,100)
		Runtime:removeEventListener("autolanReceived", clientReceived) --all incoming packets are sent to clientReceived
		Runtime:removeEventListener("autolanConnectionFailed", connectionAttemptFailed)
		Runtime:removeEventListener("autolanDisconnected", connectionAttemptFailed)	
	end
	server = require("Server")
	server:setCustomBroadcast("1 Player")
	server:startInternet()
	isServer = true
	print(" Wait client connect")
	
	--menuGroup:removeSelf()
	
	--add event listeners
	Runtime:addEventListener("autolanPlayerDropped", playerDropped)
	Runtime:addEventListener("autolanPlayerJoined", addPlayer)
	--paddleDown:addEventListener("touch", dragBodyServer) --assign bottom padle to server
	Runtime:addEventListener("autolanReceived", serverReceived)  --all incoming packets sent to serverReceived
	--Runtime:addEventListener ( "enterFrame", onFrame )
	sendFullFrameTimer = timer.performWithDelay(2000, sendFullFrame, -1)
end

local numberOfServers = 0
local function createListItem(event) --displays found servers
		 --local group = self.view 
		 print("Find server")
		 if isServer ~= true then
		 	print("Vao day") 
			local item = display.newGroup()
			item.background = display.newRoundedRect(item,display.contentWidth/5 -20,yPosBtn/3 + 120, widthButton +40 , heightButton,10 )
			item.background.strokeWidth = 3
		    item.background:setFillColor(255, 255, 255)
			item.background:setStrokeColor(255, 255, 255)
			item.text = display.newText(item,event.serverName.."    "..event.customBroadcast, display.contentWidth/5, yPosBtn/3 + 120, "Helvetica-Bold", 14 )
			print("servername:"..event.serverName)
			if(event.internet) then
				item.text:setTextColor( 0,0,0 )
			else
				item.text:setTextColor( 0 )
			end
			item.serverIP = event.serverIP		
			--attach a touch listener
			function item:tap(e)
				client:connect(self.serverIP)
				menuGroup:removeSelf()
				menuGroup = nil
			end
			item:addEventListener("tap", item)
			item.y = item.y + numberOfServers*30
			numberOfServers = numberOfServers+1
			menuGroup:insert(item)
		 end
	end
Runtime:addEventListener("autolanServerFound", createListItem)
-- listener button event
local function hostPressed()
	    hostBtn.xScale = 1.5
	    hostBtn.yScale = 1.5	
end

local function hostRelease()
		hostBtn.xScale = 1
		hostBtn.yScale = 1
		menuGroup:removeSelf();
		hostBtn.isVisible = false;
		joinBtn.isVisible = false;
		textWaiting.isVisible = true;
		removeServer.isVisible = true;
		makeServer()
		--singlePlayer.mainPlay()
end
local function joinPressed()
		-- joinBtn.label = "Scanning..."
		joinBtn.xScale = 1.5
		joinBtn.xScale = 1.5	
end

local function joinRelease()
		-- joinBtn.label = "Scanning..."
		print("hehe")
		joinBtn.xScale = 1
		joinBtn.xScale = 1
		print("Loai")
		makeClient()
		--singlePlayer.mainPlay()
end

local function backPress()
	backBtn.xScale = 1.5; backBtn.yScale = 1.5;
	
end

local function backRelease()
	backBtn.xScale = 1; backBtn.yScale = 1;
	menuGroup:removeSelf();
	storyboard.gotoScene( "menu", "fade", 100 )
	return true	-- indicates successful touch
end	

local function onRemoveServerPress()
	if(isServer) then --if we were a server before, we need to unregister all the event listeners
		Runtime:removeEventListener("autolanPlayerDropped", playerDropped)
		Runtime:removeEventListener("autolanPlayerJoined", addPlayer)
		--paddleDown:removeEventListener("touch", dragBodyServer) --assign bottom padle to server
		Runtime:removeEventListener("autolanReceived", serverReceived) --all incoming packets sent to serverReceived
		--ball:removeEventListener("collision", ballCollision)
		timer.cancel(sendFullFrameTimer)
		isServer = false
	
		hostBtn.isVisible = true;
		joinBtn.isVisible = true;
		textWaiting.isVisible = false;
		removeServer.isVisible = false;
		server:stop()
		server:disconnect();
		print("Kill Server");
		isSever = false;
	end
end

local widget = require "widget"

-- create the tableView widget

---------------------------UI OBJECTS--------------------


local function spawnMenu(group)
	--functions to handle button events
	local joinText 
	local function joinPressed()
		 joinText.text = "Scanning..."
		 makeClient()
	end
end


----create the scene-------------------
--createWalls(physicsGroup)
--paddleDown = createPaddle(physicsGroup, halfW, screenH*.95, 0)
--paddleUp = createPaddle(physicsGroup, halfW, screenH*.05, 180)
--ball = createBall(physicsGroup)
--createScoreDisplay(UIGroup)
spawnMenu(menuGroup)
local function getFullGameState()
	local state = {}
	state[1] = 2--protocol id
	state[2] = singlePlayer.getScore()
	state[3] = singlePlayer.getNumofItem1()
	state[4] = singlePlayer.getNumofItem2()
	state[5] = singlePlayer.getNumofItem3()
	print("Full State:"..state[2]..";"..state[3]..";"..state[4]..";"..state[5])
	return state
end

local function getItemState(item)
	local state={}
	state[1]=3--update item and score
	if item==1 then state[2]=singlePlayer.getNumofItem1()
	elseif item==2 then state[2]=singlePlayer.getNumofItem2()
	else  state[2]=singlePlayer.getNumofItem3()
	state[3]=singlePlayer.getScore()
	state[4]=item
	print("Update State:"..state[2]..";"..state[3]..";"..state[4])
	return state
	end
end	
----------------------------------------------------------------------------------------------
-------------------------------------SERVER SPECIFIC CODE-------------------------------------
----------------------------------------------------------------------------------------------
local numPlayers = 0
local clients = {}

playerDropped = function(event)
	local clientDropped = event.client
	--go through the table and find the client that dropped
	for i=1, numPlayers do
		if(clients[i] == clientDropped) then
			table.remove(clients, i) --remove this client
			numPlayers = numPlayers - 1
		end
	end
	server:setCustomBroadcast(numPlayers.." Players")
	--now let us try to find a spectator client to retake control of the paddle
	if(clients[1]) then
		clients[1]:sendPriority({1,1}) --initialization packet with playerID = 1 so client can control paddle
	end
	print("player dropped because", event.message)
end
addPlayer = function(event)
	local client = event.client --this is the client object, used to send messages
	print("player joined",client)
	--look for a client slot
	numPlayers = numPlayers+1
	clients[numPlayers] = client
	print("1"..";"..numPlayers)
	client:sendPriority({1,numPlayers}) --initialization packet
	print("2")
	server:setCustomBroadcast(numPlayers.." Players")
	print("shit")
	singlePlayer.mainPlay()
	client:sendPriority(getFullGameState()) --initialization packet	
	Runtime:addEventListener ( "enterFrame", onFrame1 )
end
onFrame1= function(event)
	--print("On Frame")
	if  isClient then
		--send item update packet to all clients
		if singlePlayer.onFrame()~=0 then
			print ("info:"..singlePlayer.onFrame())
		    print("vao day naz")
		    local item=singlePlayer.onFrame()
		    client:send(getItemState(item))	
		else
			print ("send full")
		    client:send(getFullGameState()) 
		 									
		end	
		--client:send("ddaaa")
	end
end



sendFullFrame = function()
	
	for i=1, numPlayers do
		clients[i]:send(getFullGameState())
	end	
end

serverReceived =  function(event)
	print("got it")
	local message = event.message
	print("message"..message)
	--since this message came from a client, it can only be of type 3: player update
	--paddleUp:setTarget(message[2])
	--now forward a differential update to all clients (some are spectators)
	--figure out packet type
	if(message[1] == 1) then
		print("got init packet")
	elseif(message[1] == 2) then
		--restoreGameState(message)
		singlePlayer.setChangeState(4)
		if message[2]~=nil then
			singlePlayer.setScorePlayer2(message[2])
		end
		if message[3]~=nil then	
			singlePlayer. setNumofItem1Player2(message[3])
		end
		if message[4]~=nil then
			singlePlayer. setNumofItem2Player2(message[4])
		end
		if message[5]~=nil then	
			singlePlayer. setNumofItem3Player2(message[5])
		end	
	elseif(message[1] == 3) then	
		singlePlayer.setChangeState(message[4])
		if message[4]==1 and message[2]~=nil then singlePlayer. setNumofItem1Player2(message[2])
		elseif message[4]==2 and message[2]~=nil then singlePlayer. setNumofItem2Player2(message[2])	
		elseif message[4]==3 and message[2]~=nil then  singlePlayer. setNumofItem3Player2(message[2])
		end
		singlePlayer.setScorePlayer2(message[3])
	end	

--[[for i=1, numPlayers do
		clients[i]:send(getFullGameState())
end--]]
end

--[[dragBodyServer = function(e)
	local body = e.target
	body.touchJoint:setTarget(e.x, body.y)
	body.targetX = e.x
	if "began" == e.phase then
		display.getCurrentStage():setFocus( body, e.id )
	elseif "ended" == e.phase or "cancelled" == e.phase then
		display.getCurrentStage():setFocus( body, nil )
	elseif "moved" ==e.phase then
		--now forward a differential update to all clients (some are spectators)
		for i=1, numPlayers do
			clients[i]:send(getDifferentialGameState())
		end	
	end
end--]]

----------------------------------------------------------------------------------------------
-------------------------------------CLIENT SPECIFIC CODE-------------------------------------
----------------------------------------------------------------------------------------------

connectionAttemptFailed = function(event)
	print("connection failed, redisplay menu")
	numberOfServers = 0
	menuGroup = display.newGroup()
	spawnMenu(menuGroup)
end

local function connectedToServer(event)
	print("connected, waiting for sync")
	singlePlayer.mainPlay()
	Runtime:addEventListener ( "enterFrame", onFrame1)
	print("done")
end
Runtime:addEventListener("autolanConnected", connectedToServer)

clientReceived = function (event)
	print("received")
	local message = event.message
	if #message==4 then
	 print("message", message, message[1], message[2],message[3],message[4])
	else 
	 print("message", message, message[1], message[2],message[3],message[4],message[5])
	end 
	--figure out packet type
	if(message[1] == 1) then
		print("got init packet")
	elseif(message[1] == 2) then
		--restoreGameState(message)
		singlePlayer.setChangeState(4)
		if message[2]~=nil then
			singlePlayer.setScorePlayer2(message[2])
		end
		if message[3]~=nil then	
			singlePlayer. setNumofItem1Player2(message[3])
		end
		if message[4]~=nil then
			singlePlayer. setNumofItem2Player2(message[4])
		end
		if message[5]~=nil then	
			singlePlayer. setNumofItem3Player2(message[5])
		end	
	elseif(message[1] == 3) then	
		singlePlayer.setChangeState(message[4])
		if message[4]==1 and message[2]~=nil then singlePlayer. setNumofItem1Player2(message[2])
		elseif message[4]==2 and message[2]~=nil then singlePlayer. setNumofItem2Player2(message[2])	
		elseif message[4]==3 and message[2]~=nil then  singlePlayer. setNumofItem3Player2(message[2])
		end
		singlePlayer.setScorePlayer2(message[3])
	end	
	
end
------------------------------------------------------
--  Author : Team B
--  Description :main scene use when play game
------------------------------------------------------



------------------- Include file ----------------
--      INSERT code here ( insert file and library )

  
---------------------------------------------------------------------------------
-- BEGINNING OF YOUR IMPLEMENTATION
---------------------------------------------------------------------------------

-- Called when the scene's view does not exist:
function scene:createScene( event )
        local group = self.view 
        groupView = group
	-- INSERT code here (e.g. start timers, load audio, start listeners, etc.)
	local background = display.newImageRect( "images/background2.png", display.contentWidth, display.contentHeight )
        --local background = display.newImage( "images/menu/backgroundCity.png", true )
	background:setReferencePoint( display.TopLeftReferencePoint  )
	background.x, background.y = 0, 0
	
	local characterBg = display.newImageRect( "images/chipheo.png", display.contentWidth/2, display.contentHeight/2 )
	characterBg:setReferencePoint( display.TopLeftReferencePoint );
	characterBg.width = 100;
	characterBg.height = 100;
	characterBg.x = display.contentWidth/3 ;
	characterBg.y = display.contentHeight/2 ;
    
	-- create a widget button (which will loads level1.lua on release)
	local titleMulti = widget.newButton{
		label = "Multiplayer Chi Pheo",
		labelColor = { default={0}, over={0} },
		--default="images/menu/lr_menu_start.png",
		width = widthButton *5/3 ,  height = heightButton,
        
	}
	
	titleMulti:setReferencePoint( display.CenterReferencePoint )
	titleMulti.x = xPosBtn
	titleMulti.y = yPosBtn/3
    -- Create button option
    hostBtn = widget.newButton{
		label = "Host",
		labelColor = { default={0}, over={0} },
		--default="images/menu/lr_menu_options.png",
		width = widthButton, height = heightButton,
        onPress =   hostPressed,
        onRelease = hostRelease
	}
	
	hostBtn:setReferencePoint( display.CenterReferencePoint )
	hostBtn.x = xPosBtn
	hostBtn.y = yPosBtn/3 + 40
    
    
    -- create button tutorial
    joinBtn  = widget.newButton{
		label="Join",
		labelColor = { default={0}, over={0} },
		--default="images/menu/lr_menu_tutorial.png",
		width = widthButton, height = heightButton,
        onPress = joinPressed,
        onRelease = joinRelease
	}
	joinBtn:setReferencePoint( display.CenterReferencePoint )
	joinBtn.x = xPosBtn
	joinBtn.y = yPosBtn/3 + 80
	
	-- Create back button 
	
	
    backBtn  = widget.newButton{
		label="Back",
		labelColor = { default={0}, over={0} },
		--default="images/menu/lr_menu_tutorial.png",
		width = widthButton/2, height = heightButton,
        onPress = backPress,
        onRelease = backRelease
	}
	backBtn:setReferencePoint( display.CenterReferencePoint )
	backBtn.x = display.contentWidth - 40
	backBtn.y = display.contentHeight - 20
	-- create button joinBtn
    textWaiting =  widget.newButton{
		label="Waiting connect",
		labelColor = { default={0}, over={0} },
		--default="images/menu/lr_menu_tutorial.png",
		width = widthButton, height = heightButton,
	}
	textWaiting:setReferencePoint( display.CenterReferencePoint )
	textWaiting.x = xPosBtn
	textWaiting.y = yPosBtn/3 + 40
	textWaiting.isVisible = false;
	
    removeServer =  widget.newButton{
		label="Remove",
		labelColor = { default={0}, over={0} },
		--default="images/menu/lr_menu_tutorial.png",
		width = widthButton, height = heightButton,
		onPress = onRemoveServerPress,
	}
	removeServer:setReferencePoint( display.CenterReferencePoint )
	removeServer.x = xPosBtn
	removeServer.y = yPosBtn/3 + 80
	removeServer.isVisible = false;	   
    -- create button online
    group:insert( background )
    group:insert( characterBg )
    group:insert( titleMulti )
    group:insert( hostBtn )
	group:insert( joinBtn )
	group:insert(textWaiting)
	group:insert(removeServer)
	group:insert(backBtn)
	
end
			


-- Called BEFORE scene has moved onscreen:
function scene:willEnterScene( event )
        local group = self.view
        
        -----------------------------------------------------------------------------

end


-- Called immediately after scene has moved onscreen:
function scene:enterScene( event )
        
end


-- Called when scene is about to move offscreen:
function scene:exitScene( event )
        local group = self.view

        -----------------------------------------------------------------------------

        --      INSERT code here (e.g. stop timers, remove listeners, unload sounds, etc.)

        -----------------------------------------------------------------------------

end


-- Called AFTER scene has finished moving offscreen:
function scene:didExitScene( event )
        local group = self.view

        ----------------------------------------------------------------------------
end


-- Called prior to the removal of scene's "view" (display group)
function scene:destroyScene( event )
        local group = self.view

        ----------------------------------------------------------------------------

        ---------------------------------------------------------------------------

end


-- Called if/when overlay scene is displayed via storyboard.showOverlay()
function scene:overlayBegan( event )
        local group = self.view
        local overlay_name = event.sceneName  -- name of the overlay scene

        -----------------------------------------------------------------------------

        --      This event requires build 2012.797 or later.

        -----------------------------------------------------------------------------

end


-- Called if/when overlay scene is hidden/removed via storyboard.hideOverlay()
function scene:overlayEnded( event )
        local group = self.view
        local overlay_name = event.sceneName  -- name of the overlay scene

        -----------------------------------------------------------------------------

        --      This event requires build 2012.797 or later.
        
        -----------------------------------------------------------------------------

end



---------------------------------------------------------------------------------
-- END OF YOUR IMPLEMENTATION
---------------------------------------------------------------------------------

-- "createScene" event is dispatched if scene's view does not exist
scene:addEventListener( "createScene", scene )

-- "willEnterScene" event is dispatched before scene transition begins
scene:addEventListener( "willEnterScene", scene )

-- "enterScene" event is dispatched whenever scene transition has finished
scene:addEventListener( "enterScene", scene )

-- "exitScene" event is dispatched before next scene's transition begins
scene:addEventListener( "exitScene", scene )

-- "didExitScene" event is dispatched after scene has finished transitioning out
scene:addEventListener( "didExitScene", scene )

-- "destroyScene" event is dispatched before view is unloaded, which can be
-- automatically unloaded in low memory situations, or explicitly via a call to
-- storyboard.purgeScene() or storyboard.removeScene().
scene:addEventListener( "destroyScene", scene )

-- "overlayBegan" event is dispatched when an overlay scene is shown
scene:addEventListener( "overlayBegan", scene )

-- "overlayEnded" event is dispatched when an overlay scene is hidden/removed
scene:addEventListener( "overlayEnded", scene )

---------------------------------------------------------------------------------
--Runtime:addEventListener( "enterFrame", move );

return scene


